/*
 * Copyright (c) 2021-2021. Gardel
 *
 * This file is part of Source2Pdf (https://gitee.com/gardel/source2pdf).
 *
 * Source2Pdf is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Source2Pdf is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Source2Pdf.  If not, see <http://www.gnu.org/licenses/>.
 */

package cn.sunxinao.source2pdf.view;

import cn.sunxinao.source2pdf.model.FileNode;
import cn.sunxinao.source2pdf.utils.TaskUtils;
import io.github.palexdev.materialfx.controls.MFXFlowlessListView;
import io.github.palexdev.materialfx.controls.MFXIconWrapper;
import io.github.palexdev.materialfx.controls.MFXTooltip;
import io.github.palexdev.materialfx.controls.cell.MFXFlowlessListCell;
import io.github.palexdev.materialfx.controls.flowless.VirtualFlow;
import io.github.palexdev.materialfx.utils.AnimationUtils;
import io.github.palexdev.materialfx.utils.NodeUtils;
import java.util.Collections;
import javafx.animation.Interpolator;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import org.kordamp.ikonli.javafx.FontIcon;
import org.kordamp.ikonli.material2.Material2RoundAL;

public class FileListCell extends MFXFlowlessListCell<FileNode> {
    protected final ObservableList<FileNode> items;

    public FileListCell(MFXFlowlessListView<FileNode> listView, FileNode data) {
        super(listView, data, 40);
        this.items = listView.getItems();
    }

    @Override
    protected void render(FileNode data) {
        getChildren().setAll(rippleGenerator, createFileBox(data));
    }

    @SuppressWarnings("unchecked")
    private HBox createFileBox(FileNode node) {
        ImageView imageView = new ImageView();
        TaskUtils.submitTask(() -> {
            Image fileIcon = node.getFileIcon();
            Platform.runLater(() -> imageView.setImage(fileIcon));
        });
        FontIcon upIcon = new FontIcon(Material2RoundAL.KEYBOARD_ARROW_UP);
        FontIcon downIcon = new FontIcon(Material2RoundAL.KEYBOARD_ARROW_DOWN);
        upIcon.setIconSize(16);
        downIcon.setIconSize(16);
        MFXIconWrapper upButton = new MFXIconWrapper(upIcon, 22);
        MFXIconWrapper downButton = new MFXIconWrapper(downIcon, 22);
        upButton.getStyleClass().addAll("list-item-btn", "list-item-btn-up");
        downButton.getStyleClass().addAll("list-item-btn", "list-item-btn-down");
        upButton.setOnMouseClicked(event -> {
            int index = items.indexOf(node);
            var virtualFlow = (VirtualFlow<FileNode, FileListCell>) getParent().getParent();
            if (index > 0) {
                virtualFlow.setDisable(true);
                var upCell = virtualFlow.getCell(index - 1);
                AnimationUtils.ParallelBuilder.build()
                    .add(AnimationUtils.KeyFrames.of(300, translateYProperty(), -getHeight(), Interpolator.EASE_OUT))
                    .add(AnimationUtils.KeyFrames.of(300, upCell.translateYProperty(), upCell.getHeight(), Interpolator.EASE_OUT))
                    .setOnFinished(e -> {
                        int i = items.indexOf(node);
                        if (i > 0) {
                            Collections.swap(items, i - 1, i);
                        }
                        virtualFlow.setDisable(false);
                    })
                    .getAnimation()
                    .play();
                event.consume();
            }
        });
        downButton.setOnMouseClicked(event -> {
            int index = items.indexOf(node);
            var virtualFlow = (VirtualFlow<FileNode, FileListCell>) getParent().getParent();
            if (index > -1 && index < items.size() - 1) {
                virtualFlow.setDisable(true);
                var downCell = virtualFlow.getCell(index + 1);
                AnimationUtils.ParallelBuilder.build()
                    .add(AnimationUtils.KeyFrames.of(300, translateYProperty(), getHeight(), Interpolator.EASE_OUT))
                    .add(AnimationUtils.KeyFrames.of(300, downCell.translateYProperty(), -downCell.getHeight(), Interpolator.EASE_OUT))
                    .setOnFinished(e -> {
                        int i = items.indexOf(node);
                        if (i > -1 && i < items.size() - 1) {
                            Collections.swap(items, i, i + 1);
                        }
                        virtualFlow.setDisable(false);
                    })
                    .getAnimation()
                    .play();
                event.consume();
            }
        });
        NodeUtils.makeRegionCircular(upButton);
        NodeUtils.makeRegionCircular(downButton);
        HBox controls = new HBox(10, upButton, downButton);
        controls.setAlignment(Pos.CENTER_RIGHT);
        Label fileNameLabel = new Label(node.getDisplayName());
        fileNameLabel.getStyleClass().add("data-label");
        fileNameLabel.setTooltip(new MFXTooltip(node.getPath().toString()));
        HBox hBox = new HBox(10, imageView, fileNameLabel, controls);
        hBox.prefWidthProperty().bind(widthProperty().subtract(24));
        HBox.setHgrow(controls, Priority.ALWAYS);
        hBox.setAlignment(Pos.CENTER_LEFT);
        return hBox;
    }

    @Override
    protected void updateSelection(MouseEvent mouseEvent) {
        // Selection disallowed
    }
}
